package org.jeecg.modules.fk.service.call;

import cn.hutool.http.Header;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.jeecg.modules.fk.vo.dto.EncryptRequestParamVO;
import org.jeecg.modules.fk.properties.TaxProperties;
import org.jeecg.modules.fk.utils.SwyAPIUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.exception.JeecgBootException;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Map;
import java.util.Objects;

/**
 * 调用
 */
@Slf4j
@Component("bszsApiBaseCall")
public class BszsApiBaseCall {
    @Resource(name = "taxProperties")
    private TaxProperties taxProperties;

    /**
     * 调用接口统一处理返回公共格式
     * <p>
     * { "success": true, "data": { "code": "0", "msg": "", "map": null, "data": "{}" }, "errCode": "0", "message": "成功" }
     *
     * @param wrap       true:包裹；false：不包裹
     * @param logFunName 调用方法名
     * @param url        请求地址
     * @param reqDto     请求参数
     * @param <T>
     * @return
     */
    public <T> String postJsonParamCall(boolean wrap, String logFunName, String url, Map<String, String> headers, T reqDto) {
        //请求数据         postJsonParamCall
        String callParamJson = JSON.toJSONString(reqDto);
        log.debug("=====>>>>> {} 地址:{}, 入参:{}", logFunName, url, callParamJson);

        String resultStr = this.postJsonParamCall(wrap, url, headers, reqDto);
        log.info("=====>>>>> {} 接口返回数据，{}", logFunName, resultStr);


        if (StringUtils.isBlank(resultStr)) {
            throw new JeecgBootException(String.format("%s接口请求异常", logFunName));
        }

        JSONObject resultJsonObject = JSON.parseObject(resultStr);
        if (!Objects.equals("0", resultJsonObject.getString("errCode"))) {
            throw new JeecgBootException(resultJsonObject.getString("message"));
        }
        if (null == resultJsonObject.getJSONObject("data")) {
            throw new JeecgBootException(String.format("%s接口请求异常!", logFunName));
        }

        JSONObject dataOutterJsonObj = resultJsonObject.getJSONObject("data");
        if (!Objects.equals("0", dataOutterJsonObj.getString("code"))) {
            throw new JeecgBootException(dataOutterJsonObj.getString("msg"));
        }
        if (StringUtils.isBlank(dataOutterJsonObj.getString("data"))) {
            throw new JeecgBootException(String.format("%s接口请求异常!!", logFunName));
        }

        return dataOutterJsonObj.getString("data");
    }

    /**
     * 调用接口统一处理返回公共格式，一层返回处理
     * <p>
     * { "success": true, "data": "", "errCode": "0", "message": "成功" }
     *
     * @param wrap       true:包裹；false：不包裹
     * @param logFunName 调用方法名
     * @param url        请求地址
     * @param reqDto     请求参数
     * @param <T>
     * @return
     */
    public <T> String postJsonParamReturnOneLevelCall(boolean wrap, String logFunName, String nsrsbh, String url, Map<String, String> headers, T reqDto) {
        //请求数据
        String callParamJson = JSON.toJSONString(reqDto);
        log.debug("=====>>>>> {} 地址:{}, 入参:{}", logFunName, url, callParamJson);

        String resultStr = this.postJsonParamCall(wrap, url, headers, reqDto);
        log.info("=====>>>>> {} 接口返回数据，{}", logFunName, resultStr);

        //异步写入调用接口日志

        if (StringUtils.isBlank(resultStr)) {
            throw new JeecgBootException(String.format("%s接口请求异常", logFunName));
        }

        JSONObject resultJsonObject = JSON.parseObject(resultStr);//社保接口返回数据
        if (!Objects.equals("0", resultJsonObject.getString("errCode"))) {
            throw new JeecgBootException(resultJsonObject.getString("message"));
        }
        return resultJsonObject.getString("data");
    }

    /**
     * json入参调用方式
     *
     * @param wrap  true:包裹；false：不包裹
     * @param param 入参
     * @param <T>
     * @return
     */
    public <T> String postJsonParamCall(boolean wrap, String url, Map<String, String> headers, T param) {
        Object paramVO = null;
        if (wrap) {
            //判断参数是否需要加密入参
            paramVO = this.getEncryptRequestParamVO(param);
        } else {
            paramVO = param;
        }

        //创建一个请求
        HttpRequest httpRequest = HttpRequest.post(url);

        //设置请求头信息
        if (headers != null && !headers.isEmpty()) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                httpRequest.header(entry.getKey(), entry.getValue());
            }
        }

        //.header(Header.CONTENT_TYPE, "application/json")
        httpRequest.header(Header.ACCEPT, "application/json")
                //.form(BeanUtil.beanToMap(param))
                .body(JSON.toJSONString(paramVO))
                .timeout(180000);//超时，毫秒

        String result = null;
        try {
            result = httpRequest.execute().body();
        } catch (cn.hutool.http.HttpException e) { //超时
            if (e.getMessage().contains("connect timed out")) {
                throw new RuntimeException("请求超时，请稍后再试！", e);
            } else {
                throw e;
            }
        }
        return result;
    }

    /**
     * 判断参数是否需要加密入参
     *
     * @param param
     * @param <T>
     * @return
     */
    private <T> Object getEncryptRequestParamVO(T param) {
        EncryptRequestParamVO encryptRequestParamVO = new EncryptRequestParamVO();
        try {
            String cipherText = SwyAPIUtils.parseCiphertextToPlaintext(JSON.toJSONString(param), this.taxProperties.getRsaModulusString(), this.taxProperties.getRsaPublicExponentString());
            encryptRequestParamVO.setMw(cipherText);

            log.info("=====>>>>>接口调用加密入参，{}", JSON.toJSONString(encryptRequestParamVO));
        } catch (Exception e) {
            log.error("办税助手登陆加密失败" + e);
            throw new JeecgBootException("办税助手登陆加密失败");
        }
        return encryptRequestParamVO;
    }

    /**
     * 调用接口统一处理返回公共格式，一层返回处理
     * <p>
     * { "success": true, "data": "", "errCode": "0", "message": "成功" }
     *
     * @param wrap       true:包裹；false：不包裹
     * @param logFunName 调用方法名
     * @param url        请求地址
     * @param reqDto     请求参数
     * @param <T>
     * @return
     */
    public <T> String postJsonParamReturnOneLevelCallOfSxy(boolean wrap, String logFunName, String nsrsbh, String url, Map<String, String> headers, T reqDto) {
        //请求数据
        String callParamJson = JSON.toJSONString(reqDto);
        log.debug("=====>>>>> {} 地址:{}, 入参:{}", logFunName, url, callParamJson);

        String resultStr = this.postJsonParamCall(wrap, url, headers, reqDto);
        log.info("=====>>>>> {} 接口返回数据，{}", logFunName, resultStr);

        //异步写入调用接口日志

        if (StringUtils.isBlank(resultStr)) {
            throw new JeecgBootException(String.format("%s接口请求异常", logFunName));
        }

////        JSONObject resultJsonObject = JSON.parseObject(resultStr);//社保接口返回数据
//        if (!Objects.equals("0", resultJsonObject.getString("errCode"))) {
//            throw new JeecgBootException( resultJsonObject.getString("message"));
//        }
//        return resultJsonObject.getString("data");
        return resultStr;
    }

}
